package com.esyoga.yoyoga.handler;

import com.esyoga.yoyoga.enums.BillTypeEn;
import com.esyoga.yoyoga.enums.UserTypeEn;
import com.esyoga.yoyoga.pojo.DTO.ContractDTO;
import com.esyoga.yoyoga.pojo.*;
import com.esyoga.yoyoga.service.*;
import com.esyoga.yoyoga.util.CutPagesUtil;
import com.esyoga.yoyoga.util.DateFormatUtil;
import com.esyoga.yoyoga.util.OrderNoUtil;
import lombok.Data;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Data
@Controller
@RequestMapping("/contract")
public class ContractHandler {
    @Resource
    ContractService contractService;
    @Resource
    TrainerService trainerService;
    @Resource
    AgreementService agreementService;
    @Resource
    private GymService gymService;
    @Resource
    private PayService payService;


    //存储预返回页面的数据对象
    private Map<String, Object> result = new HashMap<>();

    /**
     * 查询某个学员/或者某个教练的的的合约信息：合约：contract表，学员与教练之间
     * @param cState 合约状态
     * @return
     */
    @RequestMapping("/select")
    @ResponseBody
    public Map<String, Object> selectTrainersByStuId(HttpServletRequest request, Integer page, int cState){
        Object obj = request.getSession().getAttribute("user");
        UserTypeEn userTypeEn = (UserTypeEn) request.getSession().getAttribute("userTypeEn");
        if(obj==null||userTypeEn==null)return null;
        List<TContract> contracts;

        //查询学员或者教练的指定状态的合约
        switch (userTypeEn){
            case STUDENT:
                TStudent student = (TStudent)obj;
                Integer sId = student.getsId();
                contracts = contractService.selectContractBySidAndCstate(sId,cState);
                break;
            case TRAINER:
                TTrainer trainer = (TTrainer) obj;
                Integer tId = trainer.gettId();
                contracts = contractService.selectContractByTidAndCstate(tId,cState);
                break;
            default:
                return null;
        }
        //分页
        CutPagesUtil.clear();
        CutPagesUtil.setPageInfo(page,10);
        List<TContract> contractList = CutPagesUtil.getPages(contracts);
        //得到DTO的数据
        List<ContractDTO> contractDTOList = contractService.selectContractDTO(contractList);
        int total = CutPagesUtil.getTotalPage();
        result.put("total",total);
        result.put("currentMessage",contractDTOList);
        return result;
    }


    /**
     * 创建合约
     * @param tId
     * @param gId
     * @return
     * 若成功创建，则返回的map集合'result' key的值为success。如果创建失败，则'result' key的值为fail。
     * 创建失败，增加errorCode键和reason键，errorCode ：001 时 reason为 用户余额不足;
     * errorCode ：002 时 reason为 更新用户余额时出错
     * errorCode ：003 时 reason为 插入合约时出错
     */
    @PostMapping("/create")
    @ResponseBody
    public Map<String, Object> createContract(HttpServletRequest request, Integer tId, Integer gId ){
        result.put("result", "fail");
        Object obj = request.getSession().getAttribute("user");
        UserTypeEn userTypeEn = (UserTypeEn) request.getSession().getAttribute("userTypeEn");
        if(obj==null||userTypeEn==null){
            result.put("reason","当前登陆用户信息丢失，请重新登陆");
            return result;
        }
        if (userTypeEn!=UserTypeEn.STUDENT) {
            result.put("reason","没有权限");
            return result;
        }

        TStudent student = (TStudent)obj;
        Integer sId = student.getsId();
        if(sId==null||sId==0||tId==null||tId==0||gId==null||gId==0){
            result.put("result", "fail");
            result.put("reason","缺少参数");
            return result;
        }

        //判断该用户该场馆该教练知否有进行中的合约
        List<Integer> stateList = new ArrayList<>();
        stateList.add(0);
        stateList.add(1);
        List<TContract> lis = contractService.selectBysIdAndGIdAndTIdAndState(sId,gId,tId,stateList);
        if(lis!=null&&lis.size()!=0){
            //业务逻辑是教练和场馆同一时刻只能有一个未终止的合约
            result.put("reason","您在该场馆与该教练有一份进行中的合约，请勿重复发起");
            return result;
        }

        //根据教练ID查询保证金
        TTrainer trainer = trainerService.selectTrainerById(tId);
        BigDecimal margin = trainer.gettValue();
        //根据教练ID和场馆ID查询场馆抽成比例
        TTrainerAgreement trainerAgreement = agreementService.selectByGIdAndTId(gId,tId).get(0);
        double gymRatio = trainerAgreement.getTaGymratio();
        //根据场馆ID查询平台抽成比例
        TGymAgreement gymAgreement = agreementService.selectByGId(gId).get(0);
        double platformRatio = gymAgreement.getGaPlatformratio();

        TContract tContract = new TContract();
        tContract.setcSId(sId);
        tContract.setcTId(tId);
        tContract.setcGId(gId);
        tContract.setcBanlance(margin);
        tContract.setcTaGymratio(gymRatio);
        tContract.setcGaPlatformratio(platformRatio);
        tContract.setcState(0);
        tContract.setcCreatetime(DateFormatUtil.getCurrentDateString());
        //设置
        return contractService.createContract(tContract);
    }

    /**
     * 更新合约：此更新方法根据主键找到对应的合约，然后更新tContract中不为null的属性
     * 即如果需要更新某个字段，传入主键和需要更新的属性值就可以了
     * @param tContract 合约
     * @return
     */
    @PostMapping("/update")
    @ResponseBody
    @Transactional
    public Map<String, Object> updateContract(TContract tContract){
        result.put("result","failed");
        //Todo:数据库中缺少一个合同更新时间
        int res = contractService.updateContract(tContract);
        if(res>0){
            //如果更新合同状态为3已完成，有一个退还保证金的逻辑
            if(tContract.getcState()==3){
                TContract contract = contractService.selectByCId(tContract.getcId());
                BigDecimal money = contract.getcBanlance();
                //todo:差一个账单金额
                payService.updateBalanceAndInsertBillRecord(
                        BillTypeEn.RETURN,
                        OrderNoUtil.orderNoGenerate(),
                        "null",
                        money,
                        tContract.getcSId(),
                        UserTypeEn.STUDENT
                );

            }
            result.put("result","success");
        }else {
            result.put("result","failed");
        }
        return result;
    }

    /**
     * 去到合约确认页面
     * @param tId
     * @param gId
     * @return
     */
    @RequestMapping("/toComfirm")
    @ResponseBody
    public ModelAndView toComfirmPage(Integer tId, Integer gId){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("gymInfo",gymService.findGymByGid(gId));
        modelAndView.addObject("trainerInfo", trainerService.selectTrainerById(tId));
        modelAndView.setViewName("html/affirmContract.html");
        return modelAndView;
    }

    /**
     * 去到合约详情页
     * @param request
     * @return
     * @throws IOException
     */
    @PostMapping("/toContractDetail")
    @ResponseBody
    public ModelAndView toContractDetailPage(HttpServletRequest request) throws IOException {
        ModelAndView modelAndView = new ModelAndView();
        String contractData = request.getParameter("contractData");
        modelAndView.setViewName("/html/contractDetail.html");
        modelAndView.addObject("contractData", contractData);
        return modelAndView;
    }

    /**
     * 查找当前登陆的学生和与指定教练和指定场馆正在进行中的合约
     * 正在进行中指的是0,1状态
     * @param gId
     * @return
     */
    @ResponseBody
    @RequestMapping("/ongoingContract")
    public TContract selectTrainerAgreementOnging(HttpServletRequest request,Integer gId, Integer tId){
        Object obj = request.getSession().getAttribute("user");
        UserTypeEn userTypeEn = (UserTypeEn) request.getSession().getAttribute("userTypeEn");
        if(obj==null||userTypeEn==null)return null;
        List<Integer> stateList = new ArrayList<>();
        stateList.add(0);
        stateList.add(1);

        //查询教练与场馆签订的合同
        switch (userTypeEn){
            case STUDENT:
                TStudent student = (TStudent) obj;
                Integer sId = student.getsId();
                List<TContract> lis = contractService.selectBysIdAndGIdAndTIdAndState(sId,gId,tId,stateList);
                if(lis!=null&&lis.size()!=0){
                    //业务逻辑是教练和场馆同一时刻只能有一个未终止的合约
                    TContract contract =lis.get(0);
                    return contract;
                }else{
                    return null;
                }
            default:
                return null;
        }
    }
}
